project/odhcpd.git
22 hours agoRevert "dhcpv6-ia: add some noise to the T1 and T2 periods" master
Kevin Darbyshire-Bryant [Fri, 5 Dec 2025 20:51:28 +0000 (20:51 +0000)]
Revert "dhcpv6-ia: add some noise to the T1 and T2 periods"

Accidental push to wrong branch/repo

This reverts commit 81ea5bfef775b8e2d4aae9826e84a040288864df.

22 hours agoRevert "do not delegate ULA prefixes"
Kevin Darbyshire-Bryant [Fri, 5 Dec 2025 20:50:29 +0000 (20:50 +0000)]
Revert "do not delegate ULA prefixes"

Accidental push to wrong branch - oops

This reverts commit fd4714bb2dfec0fadf5b49f21487f37f4613dc0f.

22 hours agodo not delegate ULA prefixes
Kevin Darbyshire-Bryant [Sat, 30 Dec 2023 11:32:55 +0000 (11:32 +0000)]
do not delegate ULA prefixes

22 hours agodhcpv6-ia: add some noise to the T1 and T2 periods
Kevin Darbyshire-Bryant [Sun, 5 Nov 2023 15:43:27 +0000 (15:43 +0000)]
dhcpv6-ia: add some noise to the T1 and T2 periods

Without this, all the clients get the same timeouts and try to renew
addresses at the same time.  Reduce the T1 & T2 by a pseudo random 0 to
127 seconds, thus the renew attempts are likely to be spread out a bit
in time.

Signed-off-by: Kevin Darbyshire-Bryant <[email protected]>
2 days agorouter: skip if branch in PIO clear functions
Álvaro Fernández Rojas [Thu, 4 Dec 2025 14:48:44 +0000 (15:48 +0100)]
router: skip if branch in PIO clear functions

We can skip the if branch that replaces the expired/duplicated ra_pio
value in the router_clear_*_ra_pio() functions.

Suggested-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/336
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 days agorouter: optimize duplicated PIO comparison
Álvaro Fernández Rojas [Thu, 4 Dec 2025 14:38:20 +0000 (15:38 +0100)]
router: optimize duplicated PIO comparison

Compare prefix and length with a single memcmp instead of performing
separate comparisons.

Suggested-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/336
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 days agorouter: remove duplicated PIOs
Álvaro Fernández Rojas [Mon, 1 Dec 2025 10:07:43 +0000 (11:07 +0100)]
router: remove duplicated PIOs

There can be duplicated PIOs if the user changed the assigned prefix length
in the configuration.

Link: https://github.com/openwrt/odhcpd/pull/336
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 days agorouter: rename router_clear_ra_pio
Álvaro Fernández Rojas [Wed, 3 Dec 2025 07:26:33 +0000 (08:26 +0100)]
router: rename router_clear_ra_pio

This function clears the expired RA PIOs, so router_clear_expired_ra_pio
is a better name.

Link: https://github.com/openwrt/odhcpd/pull/336
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 days agorouter: improve RA PIO search logic
Álvaro Fernández Rojas [Fri, 28 Nov 2025 09:39:42 +0000 (10:39 +0100)]
router: improve RA PIO search logic

We need to properly handle when the user modifies the prefix length
assigned to an interface by:
- Checking if the prefix matches the address taking into account:
    - The biggest length of address and PIO.
    - A minimum PIO of /64.
- Updating addresses and lengths for existing PIOs.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
4 days agoformal: fix workflow permissions
George Sapkin [Wed, 26 Nov 2025 13:33:30 +0000 (15:33 +0200)]
formal: fix workflow permissions

Fix formality check permissions that are needed to post optional
summaries back to the PR.

Link: openwrt/actions-shared-workflows#64
Signed-off-by: George Sapkin <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/325
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
5 days agobuild: disable static libraries
Álvaro Fernández Rojas [Sun, 30 Nov 2025 23:41:12 +0000 (00:41 +0100)]
build: disable static libraries

Allows linking against shared json-c, which reduces the binary size and
matches the OpenWrt package binary.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
5 days agodhcpv6-ia: fix crash in dhcpv6_free_lease()
David Härdeman [Mon, 1 Dec 2025 07:37:32 +0000 (08:37 +0100)]
dhcpv6-ia: fix crash in dhcpv6_free_lease()

Note that dhcpv6_free_lease() can be called with a NULL argument e.g.
from dhcpv6_ia_handle_IAs() when iface->no_dynamic_dhcp is set and a
client without a static lease cfg tries to get a dynamic lease.

Closes: #321
Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/335
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
5 days agobuild: fix BUILD_ARGS
Álvaro Fernández Rojas [Mon, 1 Dec 2025 08:02:50 +0000 (09:02 +0100)]
build: fix BUILD_ARGS

Commit ef8de928da7f forced DHCPV4_SUPPORT and UBUS cmake options, but should
have fixed BUILD_ARGS instead (-WITH_UBUS=ON -> -DUBUS=ON).

Fixes: ef8de928da7f ("build: enable DHCPV4_SUPPORT and UBUS")
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
6 days agostatefiles: change ipv4 MAC statefile syntax
David Härdeman [Sun, 30 Nov 2025 18:14:17 +0000 (19:14 +0100)]
statefiles: change ipv4 MAC statefile syntax

This changes the MAC representation in the lease/statefile so that it
reads "aa:bb:cc:dd:ee:ff" instead of "aabbccddeeff".

No functional changes, but this makes it easier to parse the statefile
in rpcd-mod-luci (for reporting the MAC addresses in LuCI).

We should probably change lease->hwaddr to be a struct ether_addr,
to make it clearer that we only support MAC addresses as hwaddr,
but that's a topic for a different PR.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/332
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
6 days agoodhcpd: remove OAF_BOUND
David Härdeman [Thu, 27 Nov 2025 17:02:11 +0000 (18:02 +0100)]
odhcpd: remove OAF_BOUND

Replace the OAF_BOUND flag with a simple boolean.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/331
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
6 days agodhcpv6: remove OAF_TENTATIVE
David Härdeman [Sun, 23 Nov 2025 23:32:22 +0000 (00:32 +0100)]
dhcpv6: remove OAF_TENTATIVE

The flag was only set in two places, and never used. Its meaning was
also essentially the inverse of OAF_BOUND.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/331
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
6 days agoodhcpd: remove OAF_STATIC
David Härdeman [Sun, 23 Nov 2025 23:19:15 +0000 (00:19 +0100)]
odhcpd: remove OAF_STATIC

This flag does nothing more than document if lease_cfg is set in the
respective dhcpv[46]_lease structs.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/331
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
6 days agoodhcpd: remove OAF_BROKEN_HOSTNAME
David Härdeman [Sun, 23 Nov 2025 23:05:33 +0000 (00:05 +0100)]
odhcpd: remove OAF_BROKEN_HOSTNAME

A bool is quite a bit more ergonomic (as the diff for this commit
shows).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/331
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
6 days agostatefiles: remove hosts entries from statefile
David Härdeman [Sun, 23 Nov 2025 22:38:04 +0000 (23:38 +0100)]
statefiles: remove hosts entries from statefile

Further simplify statefiles.c by removing the hosts entries from the
statefile (they can be found in the dedicated hosts files instead).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/331
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
8 days agobuild: enable DHCPV4_SUPPORT and UBUS
Álvaro Fernández Rojas [Fri, 28 Nov 2025 11:48:11 +0000 (12:48 +0100)]
build: enable DHCPV4_SUPPORT and UBUS

Enable DHCPV4_SUPPORT and UBUS in order to correctly build all the source
code.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
8 days agoubus: fix shadow local variable
Álvaro Fernández Rojas [Fri, 28 Nov 2025 11:46:38 +0000 (12:46 +0100)]
ubus: fix shadow local variable

Fix leftover shadowed local variable in ubus code from commit a170d63874f2.

src/ubus.c:130:38: error: declaration of 'a' shadows a previous local [-Werror=shadow=local]
  130 |                 struct dhcpv6_lease *a, *border;
      |                                      ^
src/ubus.c:118:15: note: shadowed declaration is here
  118 |         void *a;
      |               ^

Fixes: a170d63874f2 ("src: fix shadowed local variables")
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
8 days agosrc: fix shadowed local variables
Álvaro Fernández Rojas [Fri, 28 Nov 2025 07:32:10 +0000 (08:32 +0100)]
src: fix shadowed local variables

Fix shadowed local variables and enable warning to prevent more shadowed
variables in the future.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
8 days agodhcpv6-ia: fix a crash when static lease isn't configured
David Härdeman [Thu, 27 Nov 2025 23:30:59 +0000 (00:30 +0100)]
dhcpv6-ia: fix a crash when static lease isn't configured

Quoting from https://github.com/openwrt/odhcpd/issues/321:
  [71802.880039] odhcpd[22696]: segfault at 78...

Quoting from https://forum.openwrt.org/t/odhcpd-crash-loop-when-receiving-packet/243015/69:
  [   77.761062] odhcpd[2075]: segfault at 78...

0x78 is the offset of duid_count in struct lease_cfg, so if lease_cfg is
null, we'd end up reading from address 0x78 when trying to read
lease_cfg->duid_count.

This should fix the issue. Thanks to @klipz in the forums for giving me
SSH access to an awesome test sandbox.

Closes: https://github.com/openwrt/odhcpd/issues/321
Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/328
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
8 days agodhcpv4: support IPv6-only preferred (RFC8925)
David Härdeman [Sun, 23 Nov 2025 18:17:04 +0000 (19:17 +0100)]
dhcpv4: support IPv6-only preferred (RFC8925)

This adds support for RFC8925/IPv6-only preferred to the DHCPv4 server.

Closes: https://github.com/openwrt/odhcpd/pull/235
Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/327
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv6-ia: fix realloc bug
David Härdeman [Thu, 27 Nov 2025 10:35:09 +0000 (11:35 +0100)]
dhcpv6-ia: fix realloc bug

Commit b9db4d7061a08bf82a25222074065cce71973d0c introduced a bug, the
"hostname" variable used for the realloc would shadow the real hostname
defined at the beginning of the function. Fix this by using a different
variable name.

Fixes: b9db4d7061a0 ("dhcpv6: handle realloc failure")
Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/326
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agonetlink: make it clearer that we're handling realloc correctly
David Härdeman [Sun, 23 Nov 2025 14:15:33 +0000 (15:15 +0100)]
netlink: make it clearer that we're handling realloc correctly

This doesn't really change the code, it just makes it clearer when
grepping for realloc() that failure is handled correctly.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv6: handle realloc failure
David Härdeman [Sun, 23 Nov 2025 14:12:01 +0000 (15:12 +0100)]
dhcpv6: handle realloc failure

Another realloc failure case.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoconfig: handle realloc failure in piofolder parsing
David Härdeman [Sun, 23 Nov 2025 14:00:45 +0000 (15:00 +0100)]
config: handle realloc failure in piofolder parsing

Another realloc that goes unchecked.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoconfig: fix realloc() error handling for "dhcpv6_raw" option
David Härdeman [Sun, 23 Nov 2025 13:53:35 +0000 (14:53 +0100)]
config: fix realloc() error handling for "dhcpv6_raw" option

Check the return value from realloc() to avoid leaking memory.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoconfig: fix realloc() handling for the "upstream" option
David Härdeman [Sun, 23 Nov 2025 13:50:00 +0000 (14:50 +0100)]
config: fix realloc() handling for the "upstream" option

Deal properly with realloc() failure.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoconfig: fix (S)NTP realloc handling
David Härdeman [Sun, 23 Nov 2025 13:46:49 +0000 (14:46 +0100)]
config: fix (S)NTP realloc handling

Make sure that realloc errors are dealt with properly in the (S)NTP
option parsing.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv4: iface->dhcpv4_router -> iface->dhcpv4_routers
David Härdeman [Sat, 22 Nov 2025 09:13:02 +0000 (10:13 +0100)]
dhcpv4: iface->dhcpv4_router -> iface->dhcpv4_routers

This makes it clearer that the variable stores multiple addresses, also
fix a potential realloc memleak.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoodhcpd: rename iface->search -> iface->dns_search
David Härdeman [Thu, 20 Nov 2025 16:17:49 +0000 (17:17 +0100)]
odhcpd: rename iface->search -> iface->dns_search

And fix some bugs/nits in the process, e.g.:
 - realloc() not handled properly in config.c
 - replace a number of magic values
 - in router.c, the DNSSL options has 8 bytes of superfluous padding

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoodhcpd: consistent dns naming
David Härdeman [Thu, 20 Nov 2025 15:25:26 +0000 (16:25 +0100)]
odhcpd: consistent dns naming

Rename iface->dns to iface->dns6_addrs
Rename iface->dhcpv4_dns to iface->dns4_addrs

This makes it clearer what is stored in each.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv4: remove iface->dhcpv4_bcast
David Härdeman [Thu, 20 Nov 2025 12:51:25 +0000 (13:51 +0100)]
dhcpv4: remove iface->dhcpv4_bcast

This is also covered by iface->dhcpv4_own_ip

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv4: remove iface->dhcpv4_mask
David Härdeman [Thu, 20 Nov 2025 12:47:13 +0000 (13:47 +0100)]
dhcpv4: remove iface->dhcpv4_mask

This is already covered by iface->dhcpv4_own_ip

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv4: rename iface->dhcpv4_local -> iface->dhcpv4_own_ip
David Härdeman [Wed, 19 Nov 2025 23:29:18 +0000 (00:29 +0100)]
dhcpv4: rename iface->dhcpv4_local -> iface->dhcpv4_own_ip

"local" isn't very informative, the local what?

In addition, use a struct odhpd_ipaddr instead of a struct in_addr, the
former can already store the prefix_len, broadcast and netmask address,
this will allow the separate iface->dhcpv4_bcast and iface->dhcpv4_mask
members to be removed (see subsequent patches).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv4: simplify pool determination
David Härdeman [Wed, 19 Nov 2025 18:43:36 +0000 (19:43 +0100)]
dhcpv4: simplify pool determination

This simplifies the logic to determine a dynamic dhcp pool range based
on the prefix length (when "start" and "limit" aren't set).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agonetlink: add netmask for IPv4
David Härdeman [Tue, 18 Nov 2025 07:55:41 +0000 (08:55 +0100)]
netlink: add netmask for IPv4

Add a netmask member to struct odhcpd_ipaddr, this is mostly for
convenience.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agonetlink: variable naming cleanup
David Härdeman [Tue, 18 Nov 2025 07:53:37 +0000 (08:53 +0100)]
netlink: variable naming cleanup

Correct some comments, use boolean where a boolean value is expected,
rename more "struct odhcpd_ipaddr" variables to indicate that it is a
struct odhcpd_ipaddr and indicate plural/IPv4/IPv6 in the variable
names.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv4: fix no_dynamic_dhcp
David Härdeman [Mon, 17 Nov 2025 23:32:21 +0000 (00:32 +0100)]
dhcpv4: fix no_dynamic_dhcp

This fixes the support for running with no_dynamic_dhcp in the DHCPv4
server.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoodhcpd: rename iface->addr4 -> iface->oaddrs4
David Härdeman [Mon, 17 Nov 2025 22:58:48 +0000 (23:58 +0100)]
odhcpd: rename iface->addr4 -> iface->oaddrs4

Rename iface->addr4 to iface->oaddrs4, to make it clearer from a cursory
glance that this isn't e.g. "struct in_addr" addresses but a number of
"struct odhcpd_ipaddr" addresses.

At the same time, rename iface->addr4_len to iface->oaddrs4_cnt, to make
it clear that this is a count and not e.g. an allocation length.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoodhcpd: rename prefix -> prefix_len
David Härdeman [Mon, 17 Nov 2025 22:37:50 +0000 (23:37 +0100)]
odhcpd: rename prefix -> prefix_len

Change a bunch of places where a prefix length is stored as "prefix" to
instead call the length "prefix_len", to make it clearer that it is not
a prefix that is stored.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agoodhcpd: rename union if_addr -> in46_addr
David Härdeman [Mon, 17 Nov 2025 22:11:08 +0000 (23:11 +0100)]
odhcpd: rename union if_addr -> in46_addr

Anyone reading "union if_addr" might be tempted to think it's got
something to do with an interface addr (e.g. a MAC, or something). In
reality, it's an IPv4/IPv6 addr (i.e. struct in_addr or struct
in6_addr), so rename it to make things clearer.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
9 days agodhcpv4: improve pool var naming
David Härdeman [Mon, 17 Nov 2025 21:51:34 +0000 (22:51 +0100)]
dhcpv4: improve pool var naming

The uci cfg options might have somewhat confusing names, but
that doesn't mean we have to perpetuate those names throughout the
source.

Also, move the checking of whether the pool parameters from when
we are setting up a pool to where the cfg variables are actually set
from config.

Finally, there's no need to store the pool start and end as "struct
in_addr" in struct interface, because the start and end actually aren't
IPv4 addresses.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
13 days agondp: correctness fix for BPF filter
David Härdeman [Fri, 17 Oct 2025 13:32:08 +0000 (15:32 +0200)]
ndp: correctness fix for BPF filter

Note that AF_PACKET sockets start receiving packets as soon as they are
created.  Thus, a packet can arrive between the creation of the socket
and the time the real filter is installed. Fix this using the same
technique as used in libpcap, i.e. by installing a drop-all filter,
removing any packets from the socket, then installing the real filter
later (an atomic operation which replaces the drop filter).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/319
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
13 days agodhcpv4: add BPF to dhcpv4_setup_interface()
David Härdeman [Fri, 17 Oct 2025 12:49:25 +0000 (14:49 +0200)]
dhcpv4: add BPF to dhcpv4_setup_interface()

This means the kernel won't even pass packets which we are not
interested in.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/318
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
13 days agodhcpv4: define val where it is used in dhcpv4_setup_interface()
David Härdeman [Fri, 17 Oct 2025 11:59:37 +0000 (13:59 +0200)]
dhcpv4: define val where it is used in dhcpv4_setup_interface()

This makes it a tiny bit easier to see immediately what "val" is.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/318
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
13 days agodhcpv4: simplify error handling in dhcpv4_setup_interface()
David Härdeman [Fri, 17 Oct 2025 11:57:14 +0000 (13:57 +0200)]
dhcpv4: simplify error handling in dhcpv4_setup_interface()

Remove the "ret" variable which can anyway always just be -1 on error,
and rename the "out" label to "error" to clarify that it's only used on
error.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/318
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
13 days agodhcvp4: use tmp fd in dhcpv4_setup_interface()
David Härdeman [Fri, 17 Oct 2025 11:54:50 +0000 (13:54 +0200)]
dhcvp4: use tmp fd in dhcpv4_setup_interface()

This makes the code a little bit easier to read.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/318
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
13 days agodhcpv4: replace ToS precedence
David Härdeman [Fri, 17 Oct 2025 11:43:17 +0000 (13:43 +0200)]
dhcpv4: replace ToS precedence

The IPTOS_PREC_* values are deprecated since RFC2474 §4.2.2.1 (Dec 1998)
replaced them with class selector codepoints.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/318
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
13 days agostatefiles: fix off-by-one-bug
David Härdeman [Sun, 23 Nov 2025 18:34:51 +0000 (19:34 +0100)]
statefiles: fix off-by-one-bug

The string with the final hostsfile name is "%s.%s", so we need two
extra bytes for the separating "." and for the trailing null byte.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/322
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agoall: implement RFC8910 captive portal (CP) option for DHCPv4
Paul Donald [Mon, 17 Nov 2025 19:43:15 +0000 (20:43 +0100)]
all: implement RFC8910 captive portal (CP) option for DHCPv4

https://www.rfc-editor.org/rfc/rfc8910.html

Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/315
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agoall: implement RFC8910 captive portal (CP) option
Paul Donald [Sun, 16 Nov 2025 12:47:34 +0000 (13:47 +0100)]
all: implement RFC8910 captive portal (CP) option

https://www.rfc-editor.org/rfc/rfc8910.html

RFC8910 defines a captive portal API URI for a CP client to consume.

With captive_portal_uri set to 'https://test.example.com'

Produces in RA:

ICMPv6 Option (DHCP Captive-Portal)
    Type: DHCP Captive-Portal (37)
    Length: 4 (32 bytes)
    Captive Portal: https://test.example.com

And in DHCPv6 Reply:

Captive Portal
    Option: Captive Portal (103)
    Length: 24
    Captive Portal: https://test.example.com

Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/315
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agogithub: ci: add MIPS64, PowerPC64 and RISCV64
Álvaro Fernández Rojas [Mon, 17 Nov 2025 14:58:49 +0000 (15:58 +0100)]
github: ci: add MIPS64, PowerPC64 and RISCV64

MIPS64, PowerPC64 and RISCV64 are popular OpenWrt archs.
Refactor the sizes build step to generate the table programatically.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agorouter: Modify relayed RA PIO L and RA M/O flags according to interface policy
Paul Donald [Fri, 7 Nov 2025 18:54:41 +0000 (19:54 +0100)]
router: Modify relayed RA PIO L and RA M/O flags according to interface policy

Effectively:
-clear the L flag
-apply local M and O flags if we are not DHCPv6 relay mode

h/t user @Shine-

Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/300
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agodhcpv6: prevent network loop scenario
Paul Donald [Mon, 17 Nov 2025 01:15:51 +0000 (02:15 +0100)]
dhcpv6: prevent network loop scenario

It's possible for odhcpd to talk with its (odhcp6c) self in a network loop
scenario with strange results. Prevent this by returning early.

Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/314
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agodhcpv4: simplify random address selection
David Härdeman [Sat, 11 Oct 2025 09:25:26 +0000 (11:25 +0200)]
dhcpv4: simplify random address selection

Simplify the generation of random addresses, and make the code easier
to follow, by using the same approach as in dhcpv6.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/313
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agoodhcpd: update devel-build.sh
David Härdeman [Sun, 16 Nov 2025 20:10:40 +0000 (21:10 +0100)]
odhcpd: update devel-build.sh

Now that ubus can be disabled at runtime, we can default to building
it in, making it easier to catch compile-time errors in ubus.c.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/312
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agoodhcpd: make ubus optional at runtime
David Härdeman [Sun, 16 Nov 2025 17:55:59 +0000 (18:55 +0100)]
odhcpd: make ubus optional at runtime

This is mostly for developer convenience, allowing ubus to be built in, but
disabled at will when launching odhcpd.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/312
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agoodhcpd: simplify signal handling
David Härdeman [Sun, 16 Nov 2025 13:00:36 +0000 (14:00 +0100)]
odhcpd: simplify signal handling

Currently, odhcpd's main() function will:
 - call uloop_init()
 - set up some signal handlers for SIGUSR1/SIGINT/SIGTERM
   (SIGUSR1 is ignored, the other handlers call uloop_end())
 - call odhcpd_run(), which will:
 - set up some signal handlers for SIGTERM/SIGINT/SIGHUP
   (the first two call uloop_end(), SIGHUP calls odhcpd_reload())

Note that uloop_init() will call uloop_setup_signals() which will call
uloop_setup_signals() which will install handlers for SIGINT/SIGTERM
which will set uloop_cancelled to true (e.g. the same thing that
uloop_end() does).

In other words, the signal handlers are modified three times, and since
the default "exit" action is to call uloop_end(), there's nothing that
will actually react to signals until uloop_run() is called, meaning that
the startup will be uninterruptible if e.g. ubus_init() fails since
it'll just retry in a loop with no handling of signals.

So, simplify and fix this by letting uloop handle the signals and
checking if uloop has been told to exit, removing a bunch of
special-purpose code.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/312
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
2 weeks agosrc: improve attributes
Álvaro Fernández Rojas [Thu, 13 Nov 2025 10:28:12 +0000 (11:28 +0100)]
src: improve attributes

- Properly guard odhcp6c.h attributes with `#ifndef` to avoid redefining
them when including external headers.
- Also convert the remaining __attribute__ usages to the custom
declarations.
- Consolidate custom declarations with _o_ prefix.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/307
2 weeks agosrc: consolidate and improve fallthrough
Álvaro Fernández Rojas [Fri, 14 Nov 2025 06:57:21 +0000 (07:57 +0100)]
src: consolidate and improve fallthrough

- Enable fallthrough warnings.
- Use fallthrough attribute instead of comments.
- Drop unneeded fallthroughs (no code between two case statements).

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/307
3 weeks agodhcpv6-ia: add missing limits header
Álvaro Fernández Rojas [Fri, 14 Nov 2025 16:42:35 +0000 (17:42 +0100)]
dhcpv6-ia: add missing limits header

Fix the following build error by including <limits.h>:
src/dhcpv6-ia.c: In function 'handle_addrlist_change':
src/dhcpv6-ia.c:495:53: error: 'INT_MAX' undeclared (first use in this function)
  495 |                                         a->fr_cnt = INT_MAX;
      |                                                     ^~~~~~~
src/dhcpv6-ia.c:33:1: note: 'INT_MAX' is defined in header '<limits.h>'; did you forget to '#include <limits.h>'?
   32 | #include <libubox/md5.h>
  +++ |+#include <limits.h>
   33 |
src/dhcpv6-ia.c:495:53: note: each undeclared identifier is reported only once for each function it appears in
  495 |                                         a->fr_cnt = INT_MAX;
      |                                                     ^~~~~~~

Fixes: 7136fbe390a5 ("dhcpv6-ia: split statefile handling to separate file")
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/311
3 weeks agoconfig: fix memleak during odhcpd reload
Fei Lv [Fri, 14 Nov 2025 07:31:22 +0000 (15:31 +0800)]
config: fix memleak during odhcpd reload

- The memset in close_interface reset the pios pointer before it
  could be freed, causing a memory leak. Relocate the free call
  to clean_interface to ensure proper deallocation.

- Use realloc instead of malloc in config_load_ra_pio()
  This function may be called multiple times during odhcpd reload,
  and using malloc without freeing the previous allocation was
  causing memory leaks.

Signed-off-by: Fei Lv <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/309
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agodhcpv4: update ubus DHCPv4 events/methods
David Härdeman [Mon, 10 Nov 2025 22:36:27 +0000 (23:36 +0100)]
dhcpv4: update ubus DHCPv4 events/methods

This is based on the assumption that we don't really have any consumers
of ubus DHCPv4 events (yet).

With that in mind, rename and simplify the event function (yes, we
should add a sibling function for DHCPv6 leases later).

Also, take the chance to improve some naming, and introduce additional
attributes to the ubus event/method (the interface name and the
DUID/IAID, if known).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/306
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agoodhcpd: rename dhcpv6_lease->clid[_data|_len]
David Härdeman [Mon, 10 Nov 2025 22:19:31 +0000 (23:19 +0100)]
odhcpd: rename dhcpv6_lease->clid[_data|_len]

The option is called clientid, but the option carries a DUID. So what
we're storing is a DUID, not a CLID.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/306
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agoodhcpd: rename [lease_cfg|dhcpv4_lease]->ipaddr to ipv4
David Härdeman [Mon, 10 Nov 2025 22:03:25 +0000 (23:03 +0100)]
odhcpd: rename [lease_cfg|dhcpv4_lease]->ipaddr to ipv4

"ipaddr" doesn't say if it's IPv4 or IPv6, and we want to be clear in a
dual-stack codebase.

And at the same time, use a struct in_addr to store the IPv4 address,
which is just less confusing.

Finally, remove all uses of "inet_ntoa()", which is deprecated.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/306
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agodhcpv4: use an AVL to store leases
David Härdeman [Sat, 11 Oct 2025 06:29:07 +0000 (08:29 +0200)]
dhcpv4: use an AVL to store leases

An AVL has O(log n) complexity vs O(n) for a linked list in all the
operations we care about (insertion and search).

Also, it makes the code simpler by not having to care about details like
how to sort the leases.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/306
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agogithub: ci: add powerpc arch
Álvaro Fernández Rojas [Fri, 14 Nov 2025 13:16:16 +0000 (14:16 +0100)]
github: ci: add powerpc arch

PowerPC is another popular OpenWrt arch.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agogithub: ci: add cmake build and source directories
Álvaro Fernández Rojas [Fri, 14 Nov 2025 13:14:34 +0000 (14:14 +0100)]
github: ci: add cmake build and source directories

Add cmake build and source directories to suppress the following warning:
CMake Warning:
  No source or binary directory provided. Both will be assumed to be the
  same as the current working directory, but note that this warning will
  become a fatal error in future CMake releases.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agogithub: ci: disable json-c tests
Álvaro Fernández Rojas [Fri, 14 Nov 2025 07:36:51 +0000 (08:36 +0100)]
github: ci: disable json-c tests

Disable BUILD_TESTING to save time when building json-c.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agoscripts: devel-build: disable json-c tests
Álvaro Fernández Rojas [Fri, 14 Nov 2025 07:35:18 +0000 (08:35 +0100)]
scripts: devel-build: disable json-c tests

Disable BUILD_TESTING to save time when building json-c.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agonetlink: fix typo in debug msg
David Härdeman [Tue, 11 Nov 2025 12:08:22 +0000 (13:08 +0100)]
netlink: fix typo in debug msg

As noted by @CasperVector in #115, there's a typo in netlink.c,
checking if true is true isn't very useful :)

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/305
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agosrc: fix whitespace issues
Álvaro Fernández Rojas [Mon, 10 Nov 2025 12:36:33 +0000 (13:36 +0100)]
src: fix whitespace issues

- Remove double whitespaces.
- Convert whitespace alignments to tabs.
- Fix code comments using whitespaces.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agovscode: enable indentation detection
Álvaro Fernández Rojas [Tue, 11 Nov 2025 11:44:57 +0000 (12:44 +0100)]
vscode: enable indentation detection

Fixes issues with VSCode forcing whitespaces instead of tabs for indentation.

Fixes: df1824aec66c ("vscode: add tab settings")
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agoodhcpd: add support for "ignore"
David Härdeman [Sun, 9 Nov 2025 17:36:03 +0000 (18:36 +0100)]
odhcpd: add support for "ignore"

This is inspired by @Kasoo's work in PR #234, but slightly different.

The "ip" option now takes "ignore" as a value , but it'll only disable
DHCPv4 for a matching client.

Similarly, the "hostid" option now also understands "ignore", which will
disable DHCPv6 for a matching client.

Of course, this is all based on client-reported MAC
addresses/DUIDs/client IDs/etc, so it's not actually a security feature.

Closes: https://github.com/openwrt/odhcpd/pull/234
Closes: https://github.com/openwrt/odhcpd/issues/198
Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/303
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: support per-interface hosts files
David Härdeman [Sat, 8 Nov 2025 18:52:44 +0000 (19:52 +0100)]
statefiles: support per-interface hosts files

With this change, the "hostsfile" option is changed to a "hostsdir"
option. If set, per-interface hosts files will be written to the
directory (this requires some changes to the UCI defaults in the OpenWrt
repo). This prevents the hostnames from one interface "leaking" into
other interfaces, which might not be desirable e.g. when running several
instances of dnsmasq.

dnsmasq already supports reading several hosts files from a directory
(via the "--hostsdir=" option), so some changes to dnsmasq's init script
will also be necessary (depending on whether the user wants dnsmasq to
support resolution of all hosts or just the host on a given interface).

Making hosts files (rather than odhcpd's state file) the primary
interface for dnsmasq to be made aware of active leases/hostnames is
also an important first step towards making the statefile properly
private (the other important consumer is LuCI, via its rpcd plugin),
which is necessary if we want to support persisting leases across
restarts of odhcpd (or even reboots, if writing to flash is deemed
acceptable) in the future (since I want to extend the state file to
capture the full state of leases so that they can be properly
reconstructed).

In addition, the use of "--hostsdir=" in dnsmasq would make the
"leasetrigger" unnecessary, since it just restarts dnsmasq to make it
aware of the changes to the hostsfile. That still leaves the case when
dnsmasq uses multiple instances and only wants to read a specific
hostsfile (which, AFAIK, doesn't support automatic detection of when
that specific file changes).

Closes: https://github.com/openwrt/odhcpd/issues/237
Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: don't make hostsfile dependent on statefile
David Härdeman [Sat, 8 Nov 2025 17:33:07 +0000 (18:33 +0100)]
statefiles: don't make hostsfile dependent on statefile

Right now, the hosts file will only be created if the statefile is also
configured (and that fact isn't documented in the README.md, only in
commit logs (see 4bbc6e74248feeb756bd03dc500fb4f446ccfc49).

With this patch, the hostsfile is generated whether the statefile is
configured or not.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: don't write expired leases
David Härdeman [Sat, 8 Nov 2025 17:17:34 +0000 (18:17 +0100)]
statefiles: don't write expired leases

This also aligns the behaviour of state and host files.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: simplify statefiles_write_state6()
David Härdeman [Sat, 8 Nov 2025 17:09:45 +0000 (18:09 +0100)]
statefiles: simplify statefiles_write_state6()

By collecting the addresses first and writing the hosts entries, we can
write the state line straight to the file, without having to use a
buffer as an intermediary. This also makes the ordering in the function
more logical, as it reflects the order things get written to file.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: write straight to file in statefiles_write_state4()
David Härdeman [Sat, 8 Nov 2025 16:48:00 +0000 (17:48 +0100)]
statefiles: write straight to file in statefiles_write_state4()

Instead of writing to a buffer, then to a file, just write straight to
file. This also makes the order of the steps in the function more
logical (i.e. matches the order in which things are actually written to
file).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: correct some comments/variable names
David Härdeman [Sat, 8 Nov 2025 15:17:56 +0000 (16:17 +0100)]
statefiles: correct some comments/variable names

Correct some comments and variable names in statefiles_write_state[46].

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: unify host4 writing
David Härdeman [Sat, 8 Nov 2025 14:56:30 +0000 (15:56 +0100)]
statefiles: unify host4 writing

The statefile contains host entries and state comments. Reuse the host
writing functionality for IPv4 hosts, and remove some duplication.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: unify host6 writing
David Härdeman [Sat, 8 Nov 2025 14:46:14 +0000 (15:46 +0100)]
statefiles: unify host6 writing

The statefile is a mix of state comments and hostsfile entries, reuse the
hosts writing logic when writing the statefile to reduce duplication.
(note that this has a tiny extra cost in that inet_ntop() is called
twice, that'll go away later when we drop the hostsfile style lines from
the statefile).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: group functions
David Härdeman [Sat, 8 Nov 2025 14:28:49 +0000 (15:28 +0100)]
statefiles: group functions

Move statefiles_write_state6() so that all host/state functions are
grouped together.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: add function to write IPv4 hosts
David Härdeman [Sat, 8 Nov 2025 14:24:13 +0000 (15:24 +0100)]
statefiles: add function to write IPv4 hosts

Analogous to statefiles_write_host6().

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: simplify state/host file writing
David Härdeman [Sat, 8 Nov 2025 14:08:17 +0000 (15:08 +0100)]
statefiles: simplify state/host file writing

Simplify and rename:
dhcpv6_write_ia_addrhosts() -> statefiles_write_host6()
dhcpv6_write_ia_addr() -> statefiles_write_state6()

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: move dhcpv6_ia_enum_addrs() to odhcpd.c
David Härdeman [Sat, 8 Nov 2025 13:40:39 +0000 (14:40 +0100)]
statefiles: move dhcpv6_ia_enum_addrs() to odhcpd.c

dhcpv6_ia_enum_addrs() is used in several different places (ubus,
statesfile, dhcpv6-ia), so move it to a more central location. At the
same time, rename it to odhcpd_enum_addr6().

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: add dhcpv6_lease to dhcpv6_log_ia_addr() args
David Härdeman [Sat, 8 Nov 2025 13:22:23 +0000 (14:22 +0100)]
statefiles: add dhcpv6_lease to dhcpv6_log_ia_addr() args

"lease" is more obvious than "ctxt->c" (which is a struct dhcpv6_lease).
This also means that the lease can be moved out from "struct
write_ctxt", so that the dhcpv4 and dhcpv6 code looks more similar.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: create helper functions to write leases
David Härdeman [Sat, 8 Nov 2025 12:17:58 +0000 (13:17 +0100)]
statefiles: create helper functions to write leases

Break statesfiles_write_state() into smaller parts, making it easier to
read and understand the logic of each part.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: introduce statefiles_write()
David Härdeman [Fri, 7 Nov 2025 16:58:05 +0000 (17:58 +0100)]
statefiles: introduce statefiles_write()

First, the name makes it clearer that several files might be written
(and it doesn't refer to dhcpv6 anymore). This also lays the ground for
the coming patches.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: use dirfd in dhcpv6_ia_write_statefile()
David Härdeman [Fri, 7 Nov 2025 16:53:22 +0000 (17:53 +0100)]
statefiles: use dirfd in dhcpv6_ia_write_statefile()

Similarly to the hostsfile, use a dirfd to keep track of the directory
where the statefile is stored, simplifying the code a bit and avoiding
some more allocations.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: bail early in dhcpv6_ia_write_statefile()
David Härdeman [Fri, 7 Nov 2025 16:30:51 +0000 (17:30 +0100)]
statefiles: bail early in dhcpv6_ia_write_statefile()

Bail early if config.dhcp_statefile isn't set, thus reducing the amount
of indentation in the function. The diff looks pretty gnarly, but that's
diff's fault, the actual code isn't changed at all.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agostatefiles: simplify dhcpv6_ia_write_hostsfile()
David Härdeman [Fri, 7 Nov 2025 16:25:40 +0000 (17:25 +0100)]
statefiles: simplify dhcpv6_ia_write_hostsfile()

Use a dirfd to keep track of the hostsfile directory, also make sure
that the directory is created if necessary (this is in preparation for
writing per-interface hostsfiles).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agodhcpv6-ia: split statefile handling to separate file
David Härdeman [Fri, 7 Nov 2025 15:43:26 +0000 (16:43 +0100)]
dhcpv6-ia: split statefile handling to separate file

dhcpv6-ia.c is already quite long, which makes it harder to work with.
In addition, the whole statefile machinery isn't specific to the dhcpv6
server, but shared by the dhcpv4 and dhcpv6 servers, so split it out to
its own file.

This is in preparation for some more hacking on the statefile handling.

The copyright headers on statefiles.[ch] are the result of some git
archeology, and I've taken the liberty of putting them in REUSE format,
using only the initial copyright year for each contributor (one of the
recommendations from the REUSE project).

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/302
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agosrc: replace #pragma once with defines
Álvaro Fernández Rojas [Mon, 10 Nov 2025 12:43:48 +0000 (13:43 +0100)]
src: replace #pragma once with defines

Replace #pragma once with defines since it's not standard.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agosrc: remove whitespaces at EOL
Álvaro Fernández Rojas [Mon, 10 Nov 2025 12:12:46 +0000 (13:12 +0100)]
src: remove whitespaces at EOL

These whitespaces do nothing and can be removed.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agovscode: add tab settings
Álvaro Fernández Rojas [Mon, 10 Nov 2025 12:38:04 +0000 (13:38 +0100)]
vscode: add tab settings

Add tag settings for Visual Studio Code.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
3 weeks agoodhcpd: Implement RFC9762 DHCPv6 PD Preferred flag for PIOs
Paul Donald [Sun, 9 Nov 2025 23:00:05 +0000 (00:00 +0100)]
odhcpd: Implement RFC9762 DHCPv6 PD Preferred flag for PIOs

The RFC defines the P flag for use within PIOs, and defines its meaning
as "purely a positive indicator, telling nodes that DHCPv6 PD is
available and the network prefers that nodes use it".

The RFC abstract lays out:

The (P) flag is used to indicate that the network prefers that clients
use the deployment model in RFC 9663 instead of using individual
addresses in the on-link prefix assigned using SLAAC, or DHCPv6 address
assignment.

Signed-off-by: Paul Donald <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/301
Signed-off-by: Álvaro Fernández Rojas <[email protected]>